package com.devplatform.service.impl.points;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devplatform.mapper.article.ArticleInteractionsMapper;
import com.devplatform.mapper.points.PointsDetailMapper;
import com.devplatform.mapper.points.UserPointsMapper;
import com.devplatform.pojo.article.ArticleInteractions;
import com.devplatform.pojo.points.MonthPointsSummaryDTO;
import com.devplatform.pojo.points.PointsDetail;
import com.devplatform.pojo.points.PointsReason;
import com.devplatform.pojo.points.UserPoints;
import com.devplatform.pojo.user.User;
import com.devplatform.service.points.*;
import com.devplatform.service.user.IUserService;
import com.devplatform.util.MessageUtil;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author 86156
 * @description 针对表【user_points】的数据库操作Service实现
 * @createDate 2025-09-28 10:03:14
 */
@Service
public class UserPointsServiceImpl extends ServiceImpl<UserPointsMapper, UserPoints>
        implements UserPointsService {

    @Resource
    private UserPointsMapper userPointsMapper;
    @Resource
    private PointsCommonService pointsCommonService;
    @Resource
    private PointsDetailService pointsDetailService;
    @Resource
    private PointsDetailMapper pointsDetailMapper;
    @Resource
    private PointsReasonService pointsReasonService;
    @Resource
    private UserLevelService userLevelService;
    @Resource
    private IUserService userService;
    @Resource
    private ArticleInteractionsMapper articleInteractionsMapper;
    @Resource
    private MessageUtil messageUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    //签到功能实现
    public Map<String, Object> userCheckIn(Long userId) {
        UserPoints userPoints = userPointsMapper.selectByUserId(userId);
        if (userPoints == null) {
            userPoints = new UserPoints();
            userPoints.setUserId(userId);
            userPoints.setTotalPoints(0);
            userPoints.setPoints(0);
            userPointsMapper.insert(userPoints);
        }
        //校验用户是否签到
        if (isTodayCheckIn(userId)) {
            throw new RuntimeException("今天已经签到");
        }
        int continuousDay = calculateContinuousSignDays(userId, false);
        int continuousDay2 = continuousDay + 1;
        String reasonCode;
        if (continuousDay2 % 30 == 0) {
            reasonCode = "SIGN_CONTINUOUS_30";
        } else if (continuousDay2 % 7 == 0) {
            reasonCode = "SIGN_CONTINUOUS_7";
        } else {
            reasonCode = "SIGN_DAILY";
        }
        PointsReason reason = pointsReasonService.getByReasonCode(reasonCode);
        if (reason == null) {
            throw new RuntimeException("未找到对应规则" + reasonCode);
        }
        int rewardPoints = reason.getPointsValue();//获取的积分
        //积分更新与记录
        pointsCommonService.updatePointsDetail(userId, reasonCode, rewardPoints, false);
        //用户等级更新
        userLevelService.calculateUserLevel(userId);
        String rewardTip = getCheckInRewardTip(continuousDay2);
        messageUtil.sendCheckInMessage(userId, rewardPoints, continuousDay2, rewardTip);
        return getCheckInStatus(userId);
    }

    //检验是否签到
    public boolean isTodayCheckIn(Long userId) {
        int count = pointsDetailService.countToday(userId);
        return count > 0;
    }

    public int calculateContinuousSignDays(Long userId, boolean hasCheckedInToday) {
        List<PointsDetail> reversedSignList = pointsDetailMapper.selectSignInRecordsByUserId(userId);
        if (reversedSignList == null || reversedSignList.isEmpty()) {
            return hasCheckedInToday ? 1 : 0;
        }

        int continuousDays = 0;
        LocalDate traceDate;
        LocalDate today = LocalDate.now();
        LocalDate latestSignDate = reversedSignList.get(0).getCreateTime().toLocalDate();

        if (hasCheckedInToday) {
            continuousDays = 1;
            if (latestSignDate.equals(today)) {
                traceDate = today.minusDays(1);
            } else {
                traceDate = latestSignDate.minusDays(1);
            }
        } else {
            continuousDays = 1;
            traceDate = latestSignDate.minusDays(1);
        }

        for (int i = 1; i < reversedSignList.size(); i++) {
            LocalDate currentSignDate = reversedSignList.get(i).getCreateTime().toLocalDate();

            if (currentSignDate.equals(traceDate)) {
                continuousDays++;
                traceDate = traceDate.minusDays(1);
            } else if (currentSignDate.isBefore(traceDate)) {
                break;
            }
        }

        return continuousDays;
    }


    @Cacheable(value = "userPoints", key = "#userId")
    @Override
    //按照id查询用户积分详情
    public UserPoints getByUserId(Long userId) {
        return userPointsMapper.selectByUserId(userId);
    }

    @Override
    public Map<String, Object> getUserPointsInfo(Long userId) {
        Map<String, Object> result = new HashMap<>();

        UserPoints userPoints = userPointsMapper.selectByUserId(userId);

        // 查询用户等级
        User user = userService.getById(userId);
        String levelName = userLevelService.getLevelName(user.getLevel());
        int level = user.getLevel();
        // 设置返回数据（确保 key 不为 null）
        result.put("totalPoints", userPoints != null ? userPoints.getTotalPoints() : 0);
        result.put("availablePoints", userPoints != null ? userPoints.getPoints() : 0); // 新增可用积分返回
        result.put("levelName", levelName);
        result.put("level", level);

        return result;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int incrementPoints(Long userId, Integer points) {
        UserPoints userPoints = userPointsMapper.selectByUserId(userId);
        if (userPoints == null) {
            // 初始化用户积分记录（总积分和可用积分都设为0）
            userPoints = new UserPoints();
            userPoints.setUserId(userId);
            userPoints.setTotalPoints(0);
            userPoints.setPoints(0);
            userPointsMapper.insert(userPoints);
        }
        return userPointsMapper.incrementPoints(userId, points);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exchangePointsForHot(Long userId, Long articleId, int hotValue) {
        int needPoints = hotValue * 10;
        UserPoints userPoints = userPointsMapper.selectByUserId(userId);
        if (userPoints == null || userPoints.getPoints() < needPoints) {
            throw new RuntimeException("积分不足，无法兑换");
        }
        pointsCommonService.updatePointsDetail(userId, "INCREASE_HOT", -needPoints, false);
        ArticleInteractions articleInteractions = articleInteractionsMapper.selectOne(
                new QueryWrapper<ArticleInteractions>()
                        .eq("article_id", articleId));
        articleInteractions.setArticlePoints(articleInteractions.getArticlePoints() + needPoints);
        articleInteractionsMapper.updateById(articleInteractions);
        // 发送专属兑换消息
        messageUtil.sendExchangeMessage(userId, "文章热度", needPoints, UUID.randomUUID().toString());
    }

    @Override
    public Map<String, Object> getCheckInStatus(Long userId) {
        boolean hasCheckedIn = isTodayCheckIn(userId);
        int continuousDays = calculateContinuousSignDays(userId, hasCheckedIn);

        // 新增：查询本月签到次数
        int monthCheckCount = pointsDetailMapper.countSignInByMonth(userId);
        // 新增：查询总签到次数
        int totalCheckCount = pointsDetailMapper.countTotalSignIn(userId);
        // 新增：获取签到奖励提示
        String rewardTip = getCheckInRewardTip(continuousDays);

        Map<String, Object> status = new HashMap<>();
        status.put("hasCheckedIn", hasCheckedIn);
        status.put("continuousDays", continuousDays);
        status.put("monthCheckCount", monthCheckCount);
        status.put("totalCheckCount", totalCheckCount);
        status.put("rewardTip", rewardTip);
        return status;
    }

    @Override
    public MonthPointsSummaryDTO getMonthPointsSummary(Long userId) {
        MonthPointsSummaryDTO summary = new MonthPointsSummaryDTO();
        summary.setMonthEarned(pointsDetailMapper.sumMonthEarned(userId));
        summary.setMonthSpent(pointsDetailMapper.sumMonthSpent(userId));
        return summary;
    }

    private String getCheckInRewardTip(int continuousDays) {
        if (continuousDays % 30 == 0) {
            return "获得50积分（连续30天奖励）";
        } else if (continuousDays % 7 == 0) {
            return "获得10积分（连续7天奖励）";
        } else {
            return "获得5积分（日常签到奖励）";
        }
    }
}




